﻿using Forum.Infrastructure.Util;
using Forum.Model;
using Forum.Model.Entity;
using Forum.Model.Pager;
using Forum.Model.QueryFilters;
using Forum.Model.Request;
using Forum.Model.Response;
using Forum.Repository.Extensions;
using Forum.Repository.Interface;
using Forum.Service.Interface;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;

namespace Forum.Service.Service
{
    public class PhotoService : IPhotoService
    {
        private readonly IAppRepository<Photo> _photoRepo;
        private readonly IWebHostEnvironment _environment;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="photoRepo"></param>
        /// <param name="environment"></param>
        public PhotoService(IAppRepository<Photo> photoRepo, IWebHostEnvironment environment)
        {
            _photoRepo = photoRepo;
            _environment = environment;
        }

        /// <summary>
        /// 查询所有图片
        /// </summary>
        /// <returns></returns>
        public List<Photo> GetAll()
        {
            return _photoRepo.GetList();
        }

        /// <summary>
        /// 分页查询图片
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public IPagedList<Photo> GetPagedList(QueryParameters param)
        {
            var querySet = _photoRepo.SugarQueryable;

            // 关键词过滤
            if (!string.IsNullOrEmpty(param.Search))
            {
                querySet = querySet.Where(a => a.Title.Contains(param.Search));
            }
            // 排序
            if (!string.IsNullOrEmpty(param.SortBy))
            {
                // 是否升序
                var ascending = !param.SortBy.StartsWith("-") ? " asc" : " desc";
                var orderByProperty = param.SortBy.Trim('-');

                querySet = querySet.OrderBy(orderByProperty + ascending);
            }
            var postList = querySet.ToPage(param.Page, param.PageSize);

            foreach (var photo in postList)
            {
                photo.FilePath = $"{SystemConfig.imageUrl}/media/photo/compress/{photo.FilePath}";
            }
            return postList;
        }

        /// <summary>
        /// 根据ID查询图片信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Photo? GetById(string id)
        {
            var photo = _photoRepo.FindEntity(a => a.Id == id);
            photo.FilePath = $"{SystemConfig.imageUrl}/media/photo/{photo.FilePath}";
            return photo;
        }

        /// <summary>
        /// 添加图片
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="photoFile"></param>
        /// <returns></returns>
        public Photo Add(PhotoReq dto, IFormFile photoFile)
        {
            var photoId = GuidUtils.GuidTo16String();
            var photo = new Photo
            {
                Id = photoId,
                Title = dto.Title,
                CreateTime = DateTime.Now,
                Location = dto.Location,
                FilePath = $"{photoId}.jpg"
            };
            //获取图片物理地址
            var path = GetPhotoFilePath($"{photoId}.jpg");

            const int maxWidth = 2000;
            const int maxHeight = 2000;
            using (var image = Image.Load(photoFile.OpenReadStream()))
            {
                if (image.Width > maxWidth)
                    image.Mutate(a => a.Resize(maxWidth, 0));
                if (image.Height > maxHeight)
                    image.Mutate(a => a.Resize(0, maxHeight));
                image.Save(path);
            }

            using (var fs = new FileStream(path, FileMode.Create))
            {
                photoFile.CopyTo(fs);
            }
            //获取图片的宽和高
            photo = BuildPhotoData(photo, path);

            //获取缩略图保存地址
            var newPath = GetPhotoFileCompressPath($"{photoId}.jpg");
            //保存缩略图
            ImgHelper.CompressImage(path, newPath);

            _photoRepo.Insert(photo);
            return photo;
        }

        /// <summary>
        /// 获取图片的物理存储路径
        /// </summary>
        /// <param name="photo"></param>
        /// <returns></returns>
        private string GetPhotoFilePath(string photoPath)
        {
            string rootPath = _environment.WebRootPath;
            if (string.IsNullOrEmpty(rootPath))
                rootPath = Appsettings.App("FileBaseUrl");

            var path = Path.Combine(rootPath, "media", "photo");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            return Path.Combine(path, photoPath);
        }

        /// <summary>
        /// 获取压缩后的路径
        /// </summary>
        /// <param name="photoPath"></param>
        /// <returns></returns>
        private string GetPhotoFileCompressPath(string photoPath)
        {
            string rootPath = _environment.WebRootPath;
            if (string.IsNullOrEmpty(rootPath))
                rootPath = Appsettings.App("FileBaseUrl");

            var path = Path.Combine(rootPath, "media", "photo", "compress");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            return Path.Combine(path, photoPath);
        }

        /// <summary>
        /// 重建图片数据（扫描图片的大小等数据）
        /// </summary>
        /// <param name="photo"></param>
        /// <returns></returns>
        private Photo BuildPhotoData(Photo photo, string path)
        {
            var imgInfo = Image.Identify(path);
            photo.Width = imgInfo.Width;
            photo.Height = imgInfo.Height;

            return photo;
        }

        /// <summary>
        /// 获取图片瀑布流
        /// </summary>
        /// <returns></returns>
        public List<WaterfallResp> GetWaterfallList()
        {
            var list = _photoRepo.GetList();

            List<WaterfallResp> imgList = new List<WaterfallResp>();
            foreach (var item in list)
            {
                WaterfallResp img = new WaterfallResp();
                img.imgUrl = $"{SystemConfig.imageUrl}/media/photo/compress/{item.FilePath}";
                img.avatar = $"{SystemConfig.imageUrl}/media/photo/compress/{item.FilePath}";
                img.user = "curry";
                img.title = item.Title;
                imgList.Add(img);
            }

            return imgList;
        }
    }
}
